package calc;

import java.io.IOException;
import java.util.Map;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTreeNodeStream;

import uk.ac.ed.ph.snuggletex.SnuggleEngine;
import uk.ac.ed.ph.snuggletex.SnuggleInput;
import uk.ac.ed.ph.snuggletex.SnuggleSession;

import calc.BasicArithmeticEquParser.evaluator_return;
import calc.BasicArithmeticEquParser.problem_return;
import calc.equations.*;

public class EquationTest {
	
	AdditionEquation add = new AdditionEquation();
	SubtractionEquation sub = new SubtractionEquation();
	MultiplicationEquation mult = new MultiplicationEquation();
	
	public static void main(String[] args) throws RecognitionException{
		EquationTest test = new EquationTest();
		/*
		test.addTest();
		test.subTest();
		test.addSubTest();
		test.multTest();
		test.multAdditionTest();
		test.multSubtractionTest();
		*/
		
		test.recognitionTest();
	}
	
	public void addTest() throws RecognitionException{
		System.out.println("Addition Test:");
		runTest(add);
	}
	
	public void subTest() throws RecognitionException{
		System.out.println("Subtraction Test:");
		runTest(sub);	
	}
	
	public void addSubTest() throws RecognitionException{
		System.out.println("Addition & Subtraction Test 1:");
		AdditionEquation addSub = new AdditionEquation(sub.getRandomTemplate());
		runTest(addSub);
		System.out.println("Addition & Subtraction Test 2:");
		SubtractionEquation subAdd = new SubtractionEquation(add.getRandomTemplate());
		runTest(subAdd);
	}
	
	public void multTest() throws RecognitionException{
		System.out.println("Multiplication Test:");
		runTest(mult);
	}
	
	public void multAdditionTest() throws RecognitionException{
		System.out.println("Multiplication & Addition Test 1:");
		MultiplicationEquation multAdd = new MultiplicationEquation(add.getRandomTemplate());
		runTest(multAdd);
		System.out.println("Multiplication & Addition Test 2:");
		AdditionEquation addMult = new AdditionEquation(mult.getRandomTemplate());
		runTest(addMult);
	}
	
	public void multSubtractionTest() throws RecognitionException{
		System.out.println("Multiplication & Subtraction Test 1:");
		MultiplicationEquation multSub = new MultiplicationEquation(sub.getRandomTemplate());
		runTest(multSub);
		System.out.println("Multiplication & Subtraction Test 2:");
		SubtractionEquation subMult = new SubtractionEquation(mult.getRandomTemplate());
		runTest(subMult);
	}
	
	public void recognitionTest() throws RecognitionException{
		System.out.println("Addition Equation: <add>");
		runTest("<add>");
		System.out.println("\nSubtraction Equation: <sub>");
		runTest("<sub>");
		System.out.println("\nMultiplication Equation: <mult>");
		runTest("<mult>");
	}
	
	public void runTest(Equation testEqu) throws RecognitionException{
		String equ = testEqu.getRandomTemplate();
		CharStream charStream = new ANTLRStringStream(equ);
		BasicArithmeticEquLexer lexer = new BasicArithmeticEquLexer(charStream);
		TokenStream tokenStream = new CommonTokenStream(lexer);
		BasicArithmeticEquParser parser = new BasicArithmeticEquParser(tokenStream);
		evaluator_return evaluator = parser.evaluator();
		
		//Prints out the tree
		System.out.println(evaluator.tree.toStringTree());
		CommonTreeNodeStream nodeStream = new CommonTreeNodeStream(evaluator.tree);
		GrammarEvaluator walker = new GrammarEvaluator(nodeStream);
		
		//The result of the expression
		int result = walker.evaluator();
		
		//The values of each variable
		Map<String, Integer> variables = walker.variables;

		//System.out.println("Template: " + equ);
	    String tempToEqu[] = new String[equ.length()];
	    for(int i=0; i < tempToEqu.length; i++){
	    	tempToEqu[i] = "" + equ.charAt(i);
	    	if(variables.containsKey(tempToEqu[i])){
	    		tempToEqu[i] = "" + variables.get(tempToEqu[i]); 
	    	}
	    }
		
	    String tempToEquation = "";
	    
	    for(int j = 0; j < tempToEqu.length; j++){
	    	tempToEquation = tempToEquation + tempToEqu[j];
	    }
	    
	    Problem problem = new Problem(equ, tempToEquation, result);
	    
	    System.out.println(problem.toString());
	    System.out.println("MathML:" + makeImage(problem));
	}
	
	public void runTest(String equ) throws RecognitionException{
		CharStream charStream = new ANTLRStringStream(equ);
		BasicArithmeticEquLexer lexer = new BasicArithmeticEquLexer(charStream);
		TokenStream tokenStream = new CommonTokenStream(lexer);
		BasicArithmeticEquParser parser = new BasicArithmeticEquParser(tokenStream);
		problem_return problem = parser.problem();
		CommonTreeNodeStream nodeStream = new CommonTreeNodeStream(problem.tree);
		GrammarEvaluator walker = new GrammarEvaluator(nodeStream);
		runTest(walker.problem());
	}
	
	public String makeImage(Problem problem){
		/* Create vanilla SnuggleEngine and new SnuggleSession */
		SnuggleEngine engine = new SnuggleEngine();
		SnuggleSession session = engine.createSession();

		/* Parse some very basic Math Mode input */
		SnuggleInput input = new SnuggleInput("$$ " + problem.getProblem() + " $$");
		try {
			session.parseInput(input);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		/* Convert the results to an XML String, which in this case will
		 * be a single MathML <math>...</math> element. */
		String xmlString = session.buildXMLString();
		//System.out.println("Input " + input.getString() + " was converted to:\n" + xmlString);
		
		return xmlString;
	}
}
